home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume89
/
unix
/
rcs.11
< prev
next >
Wrap
Internet Message Format
|
1989-11-19
|
91KB
Path: xanth!samsung!shadooby!mailrus!cs.utexas.edu!sun-barr!newstop!sun!swap!page
From: page%swap@Sun.COM (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v89i226: rcs - revision control system, Part11/14
Message-ID: <128102@sun.Eng.Sun.COM>
Date: 19 Nov 89 09:25:50 GMT
Sender: news@sun.Eng.Sun.COM
Lines: 3293
Approved: page@sun.com
Submitted-by: rsbx@cbmvax.commodore.com (Raymond S. Brand)
Posting-number: Volume 89, Issue 226
Archive-name: unix/rcs.11
# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
# rcs/rcs.rcsfiles/rcssyn.c,v
# rcs/rcs.rcsfiles/rcsutil.c,v
# rcs/rcs.rcsfiles/rlog.c,v
# This is archive 11 of a 14-part kit.
# This archive created: Sun Nov 19 01:12:11 1989
if `test ! -d rcs`
then
mkdir rcs
echo "mkdir rcs"
fi
if `test ! -d rcs/rcs.rcsfiles`
then
mkdir rcs/rcs.rcsfiles
echo "mkdir rcs/rcs.rcsfiles"
fi
echo "extracting rcs/rcs.rcsfiles/rcssyn.c,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcssyn.c,v
Xhead 4.6;
Xbranch 4.6.2;
Xaccess ;
Xsymbols amiga_rcs:4.6.2 cbmvax_source:4.6.1 uunet_june89_dist:4.6;
Xlocks ; strict;
Xcomment @ * @;
X
X
X4.6
Xdate 89.05.01.15.13.32; author narten; state Exp;
Xbranches 4.6.1.1 4.6.2.1;
Xnext ;
X
X4.6.1.1
Xdate 89.08.11.01.43.06; author rsbx; state Exp;
Xbranches ;
Xnext ;
X
X4.6.2.1
Xdate 89.10.13.19.19.15; author rsbx; state Exp;
Xbranches ;
Xnext 4.6.2.2;
X
X4.6.2.2
Xdate 89.10.15.15.45.04; author rsbx; state Exp;
Xbranches ;
Xnext ;
X
X
Xdesc
X@RCS file input.
X@
X
X
X
X4.6
Xlog
X@checked in with -k by rsbx at 89.08.10.16.23.06.
X@
Xtext
X@/*
X * RCS file input
X */
X#ifndef lint
Xstatic char rcsid[]= "$Id: rcssyn.c,v 4.6 89/05/01 15:13:32 narten Exp $ Purdue CS";
X#endif
X/*********************************************************************************
X * Syntax Analysis.
X * Keyword table
X * Testprogram: define SYNDB
X * Compatibility with Release 2: define COMPAT2
X *********************************************************************************
X */
X
X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Walter Tichy.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X * Report all problems and direct all questions to:
X * rcs-bugs@@cs.purdue.edu
X *
X
X
X
X
X
X
X
X*/
X
X
X/* $Log: rcssyn.c,v $
X * Revision 4.6 89/05/01 15:13:32 narten
X * changed copyright header to reflect current distribution rules
X *
X * Revision 4.5 88/11/08 12:00:37 narten
X * changes from eggert@@sm.unisys.com (Paul Eggert)
X *
X * Revision 4.5 88/08/09 19:13:21 eggert
X * Allow cc -R; remove lint.
X *
X * Revision 4.4 87/12/18 11:46:16 narten
X * more lint cleanups (Guy Harris)
X *
X * Revision 4.3 87/10/18 10:39:36 narten
X * Updating version numbers. Changes relative to 1.1 actually relative to
X * 4.1
X *
X * Revision 1.3 87/09/24 14:00:49 narten
X * Sources now pass through lint (if you ignore printf/sprintf/fprintf
X * warnings)
X *
X * Revision 1.2 87/03/27 14:22:40 jenkins
X * Port to suns
X *
X * Revision 1.1 84/01/23 14:50:40 kcs
X * Initial revision
X *
X * Revision 4.1 83/03/28 11:38:49 wft
X * Added parsing and printing of default branch.
X *
X * Revision 3.6 83/01/15 17:46:50 wft
X * Changed readdelta() to initialize selector and log-pointer.
X * Changed puttree to check for selector==DELETE; putdtext() uses DELNUMFORM.
X *
X * Revision 3.5 82/12/08 21:58:58 wft
X * renamed Commentleader to Commleader.
X *
X * Revision 3.4 82/12/04 13:24:40 wft
X * Added routine gettree(), which updates keeplock after reading the
X * delta tree.
X *
X * Revision 3.3 82/11/28 21:30:11 wft
X * Reading and printing of Suffix removed; version COMPAT2 skips the
X * Suffix for files of release 2 format. Fixed problems with printing nil.
X *
X * Revision 3.2 82/10/18 21:18:25 wft
X * renamed putdeltatext to putdtext.
X *
X * Revision 3.1 82/10/11 19:45:11 wft
X * made sure getc() returns into an integer.
X */
X
X
X
X/*
X#define COMPAT2
X/* version COMPAT2 reads files of the format of release 2 and 3, but
X * generates files of release 3 format. Need not be defined if no
X * old RCS files generated with release 2 exist.
X */
X/*
X#define SYNDB
X/* version SYNDB is for debugging the syntax analysis for RCS files.
X * SYNDB performs additional error checks.
X */
X/*
X#define SYNTEST
X/* version SYNTEST inputs a RCS file and then prints out its internal
X * data structures.
X*/
X
X#include "rcsbase.h"
Xextern FILE * finptr; /*RCS input file*/
Xextern char * getid();
Xextern struct hshentry * getnum();
Xextern int getkey();
Xextern int getlex();
Xextern readstring();
Xextern savestring();
X
X/* forward */
Xchar * getkeyval();
X
X/* keyword table */
X
Xchar Kaccess[] = "access";
Xchar Kauthor[] = "author";
Xchar Kbranch[] = "branch";
Xchar Kbranches[] = "branches";
Xchar Kcomment[] = "comment";
Xchar Kdate[] = "date";
Xchar Kdesc[] = "desc";
Xchar Khead[] = "head";
Xchar Klocks[] = "locks";
Xchar Klog[] = "log";
Xchar Knext[] = "next";
Xchar Kstate[] = "state";
Xchar Kstrict[] = "strict";
X#ifdef COMPAT2
Xchar Ksuffix[] = "suffix";
X#endif
Xchar Ksymbols[] = "symbols";
Xchar Ktext[] = "text";
X
X#define COMMLENGTH 20
Xchar Commleader[COMMLENGTH];
Xchar * Comment;
Xstruct access * AccessList;
Xstruct access * LastAccess;
Xstruct assoc * Symbols;
Xstruct assoc * LastSymbol;
Xstruct lock * Locks;
Xstruct lock * LastLock;
Xint StrictLocks;
Xstruct hshentry * Head;
Xstruct hshentry * Dbranch;
Xint TotalDeltas;
X
X
X
Xgetadmin()
X/* Function: Reads an <admin> and initializes the globals
X * AccessList, LastAccess, Symbols, LastSymbol,
X * Locks, LastLock, StrictLocks, Head, Comment, TotalDeltas;
X */
X{
X register char * id;
X struct access * newaccess;
X struct assoc * newassoc;
X struct lock * newlock;
X struct hshentry * delta;
X
X Comment="";
X AccessList=LastAccess=nil;
X Symbols=LastSymbol=nil;
X Locks=LastLock=nil;
X Dbranch = Head = nil;
X TotalDeltas=0;
X
X if (!getkey(Khead)) fatserror("Missing head");
X Head=getnum();
X# ifdef SYNDB
X if (Head&&((countnumflds(Head->num)%2)!=0))
X serror("Delta number required for head");
X# endif
X if (!getlex(SEMI)) serror("Missing ';' after head");
X
X if (getkey(Kbranch)) { /* optional */
X Dbranch=getnum();
X if (!getlex(SEMI)) serror("Missing ';' after branch list");
X }
X
X
X#ifdef COMPAT2
X /* read suffix. Only in release 2 format */
X if (getkey(Ksuffix)) {
X if (nexttok==STRING) {
X readstring(); nextlex(); /*through away the suffix*/
X } elsif(nexttok==ID) {
X nextlex();
X }
X if (!getlex(SEMI)) serror("Missing ';' after %s",Ksuffix);
X }
X#endif
X
X if (!getkey(Kaccess)) fatserror("Missing access list");
X while (id=getid()) {
X newaccess = (struct access *)talloc(sizeof(struct access));
X newaccess->login = id;
X newaccess->nextaccess = nil;
X if (AccessList == nil) {
X AccessList=LastAccess=newaccess;
X } else {
X LastAccess=LastAccess->nextaccess=newaccess;
X }
X }
X if (!getlex(SEMI)) serror("Missing ';' after access list");
X
X if (!getkey(Ksymbols)) fatserror("Missing symbols");
X while (id = getid()) {
X if (!getlex(COLON))
X serror("Missing ':' in symbolic name definition");
X if (!(delta=getnum())) {
X serror("Missing number in symbolic name definition");
X } else { /*add new pair to association list*/
X newassoc=(struct assoc *)talloc(sizeof(struct assoc));
X newassoc->symbol=id;
X newassoc->delta=delta;
X newassoc->nextassoc=nil;
X if (Symbols == nil) {
X Symbols=LastSymbol=newassoc;
X } else {
X LastSymbol=LastSymbol->nextassoc=newassoc;
X }
X }
X }
X if (!getlex(SEMI)) serror("Missing ';' after symbolic names");
X
X if (!getkey(Klocks)) serror("Missing locks");
X while (id = getid()) {
X if (!getlex(COLON))
X serror("Missing ':' in lock");
X if (!(delta=getnum())) {
X serror("Missing number in lock");
X } else { /*add new pair to lock list*/
X# ifdef SYNDB
X if ((countnumflds(delta->num)%2)!=0)
X serror("Delta number required for lock");
X# endif
X newlock=(struct lock *)talloc(sizeof(struct lock));
X newlock->login=id;
X newlock->delta=delta;
X newlock->nextlock=nil;
X if (Locks == nil) {
X Locks=LastLock=newlock;
X } else {
X LastLock=LastLock->nextlock=newlock;
X }
X }
X }
X if (!getlex(SEMI)) serror("Missing ';' after locks");
X if (!getkey(Kstrict)) {
X StrictLocks = false;
X } else {
X StrictLocks = true;
X if (!getlex(SEMI)) serror("Missing ';' after keyword %s",Kstrict);
X }
X if (getkey(Kcomment) && (nexttok==STRING)) {
X VOID savestring(Commleader,COMMLENGTH);nextlex();
X Comment=Commleader;
X if (!getlex(SEMI)) serror("Missing ';' after %s",Kcomment);
X }
X}
X
X
X
Xgetdelta()
X/* Function: reads a delta block.
X * returns false if the current block does not start with a number.
X */
X{
X register struct hshentry * Delta, * num;
X struct branchhead * LastBranch, * NewBranch;
X
X if (!(Delta=getnum())) return false;
X# ifdef SYNDB
X if ((countnumflds(Delta->num)%2)!=0)
X serror("Delta number required");
X# endif
X
X hshenter = false; /*Don't enter dates into hashtable*/
X Delta->date = getkeyval(Kdate, NUM, false);
X hshenter=true; /*reset hshenter for revision numbers.*/
X
X Delta->author = getkeyval(Kauthor, ID, false);
X
X Delta->state = getkeyval(Kstate, ID, true);
X
X if (!getkey(Kbranches)) fatserror("Missing branches");
X Delta->branches = LastBranch=nil;
X while (num=getnum()) {
X# ifdef SYNDB
X if ((countnumflds(num->num)%2)!=0)
X serror("Delta number required");
X# endif
X NewBranch = (struct branchhead *)talloc(sizeof(struct branchhead));
X NewBranch->hsh = num;
X NewBranch->nextbranch = nil;
X if (LastBranch == nil) {
X Delta->branches=LastBranch=NewBranch;
X } else {
X LastBranch=LastBranch->nextbranch=NewBranch;
X }
X }
X if (!getlex(SEMI)) serror("Missing ';' after branches");
X
X if (!getkey(Knext)) fatserror("Missing next");
X Delta->next=num=getnum();
X# ifdef SYNDB
X if (num&&((countnumflds(num->num)%2)!=0))
X serror("Delta number required");
X# endif
X if (!getlex(SEMI)) serror("Missing ';' after next");
X Delta->log=Delta->lockedby = nil;
X Delta->selector = '\0';
X TotalDeltas++;
X return (true);
X}
X
X
Xgettree()
X/* Function: Reads in the delta tree with getdelta(), then
X * updates the lockedby fields.
X */
X{ struct lock * currlock;
X while (getdelta());
X currlock=Locks;
X while (currlock) {
X currlock->delta->lockedby = currlock->login;
X currlock = currlock->nextlock;
X }
X}
X
X
Xgetdesc(prdesc)
Xint prdesc;
X/* Function: read in descriptive text
X * nexttok is not advanced afterwards.
X * if prdesc==true, the text is printed to stdout.
X */
X{
X
X if (!getkey(Kdesc) || (nexttok!=STRING)) fatserror("Missing descriptive text");
X if (prdesc)
X printstring(); /*echo string*/
X else readstring(); /*skip string*/
X}
X
X
X
X
X
X
Xchar * getkeyval(keyword, token, optional)
Xenum tokens token; char * keyword; int optional;
X/* reads a pair of the form
X * <keyword> <token> ;
X * where token is one of <id> or <num>. optional indicates whether
X * <token> is optional. A pointer to
X * the acutal character string of <id> or <num) is returned.
X * Getkeyval terminates the program on missing keyword or token, continues
X * on missing ;.
X */
X{
X register char * val;
X
X if (!getkey(keyword)) {
X fatserror("Missing %s", keyword);
X }
X if (nexttok==token) {
X val = NextString;
X nextlex();
X } else {
X if (!optional) {fatserror("Missing %s", keyword); }
X else val = nil;
X }
X if (!getlex(SEMI)) serror("Missing ';' after %s",keyword);
X return(val);
X}
X
X
X
X
Xputadmin(fout)
Xregister FILE * fout;
X/* Function: Print the <admin> node read with getadmin() to file fout.
X * Assumption: Variables AccessList, Symbols, Locks, StrictLocks,
X * and Head have been set.
X */
X{ struct assoc * curassoc;
X struct lock * curlock;
X struct access * curaccess;
X register char * sp;
X
X VOID fputs(Khead,fout); VOID fputs(" ",fout);
X if (Head) VOID fputs(Head->num,fout);
X
X VOID fprintf(fout,";\n%s ",Kbranch);
X if (Dbranch) VOID fputs(Dbranch->num,fout);
X
X VOID fprintf(fout,";\n%s ",Kaccess);
X curaccess = AccessList;
X if (curaccess==nil) VOID putc(' ',fout);
X while (curaccess) {
X VOID putc(' ',fout);
X VOID fputs(curaccess->login,fout);
X curaccess = curaccess->nextaccess;
X }
X VOID fprintf(fout,";\n%s ",Ksymbols);
X curassoc = Symbols;
X if (curassoc==nil) VOID putc(' ',fout);
X while (curassoc) {
X VOID fprintf(fout," %s:%s",curassoc->symbol, curassoc->delta->num);
X curassoc = curassoc->nextassoc;
X }
X VOID fprintf(fout,";\n%s ",Klocks);
X curlock = Locks;
X if (curlock==nil) VOID putc(' ',fout);
X while (curlock) {
X VOID fprintf(fout," %s:%s",curlock->login, curlock->delta->num);
X curlock = curlock->nextlock;
X }
X if (StrictLocks) VOID fprintf(fout,"; %s",Kstrict);
X VOID fprintf(fout,";\n%s %c",Kcomment,SDELIM);
X if((sp=Comment)!=nil) {
X while (*sp) if (putc(*sp++,fout)==SDELIM) VOID putc(SDELIM,fout);
X }
X VOID fprintf(fout,"%c;\n\n",SDELIM);
X}
X
X
X
X
Xputdelta(node,fout)
Xregister struct hshentry * node;
Xregister FILE * fout;
X/* Function: prints a <delta> node to fout;
X */
X{ struct branchhead * nextbranch;
X
X if (node == nil) return;
X
X VOID fprintf(fout,"\n%s\n",node->num);
X VOID fprintf(fout,"%s %s; %s %s; %s ",
X Kdate,node->date,Kauthor,node->author,Kstate);
X if (node->state!=nil) VOID fputs(node->state,fout);
X VOID fputs(";\nbranches",fout);
X nextbranch = node->branches;
X if (nextbranch==nil) VOID putc(' ',fout);
X while (nextbranch) {
X VOID putc(' ',fout);
X VOID fputs(nextbranch->hsh->num,fout);
X nextbranch = nextbranch->nextbranch;
X }
X
X VOID fprintf(fout,";\n%s ",Knext);
X if (node->next!=nil) VOID fputs(node->next->num,fout);
X VOID fputs(";\n",fout);
X
X}
X
X
X
X
Xputtree(root,fout)
Xstruct hshentry * root;
Xregister FILE * fout;
X/* Function: prints the delta tree in preorder to fout, starting with root.
X */
X{ struct branchhead * nextbranch;
X
X if (root==nil) return;
X
X if (root->selector !=DELETE)putdelta(root,fout);
X /* selector DELETE means deleted; set by rcs -o */
X
X puttree(root->next,fout);
X
X nextbranch = root->branches;
X while (nextbranch) {
X puttree(nextbranch->hsh,fout);
X nextbranch = nextbranch->nextbranch;
X }
X}
X
X
X
Xint putdtext(num,log,srcfilename,fout)
Xchar * num, * log, * srcfilename; FILE * fout;
X/* Function: write a deltatext-node to fout.
X * num points to the deltanumber, log to the logmessage, and
X * sourcefile contains the text. Doubles up all SDELIMs in both the
X * log and the text; Makes sure the log message ends in \n.
X * returns false on error.
X */
X{
X register char * sp;
X register int c;
X register FILE * fin;
X
X VOID fprintf(fout,DELNUMFORM,num,Klog);
X /* put log */
X VOID putc(SDELIM,fout);
X sp=log;
X while (*sp) if (putc(*sp++,fout)==SDELIM) VOID putc(SDELIM,fout);
X if (*(sp-1)!='\n') VOID putc('\n', fout); /*append \n if necessary*/
X /* put text */
X VOID fprintf(fout, "%c\n%s\n%c",SDELIM,Ktext,SDELIM);
X if ((fin=fopen(srcfilename,"r"))==NULL) {
X error("Can't open source file %s",srcfilename);
X return false;
X }
X while ((c=fgetc(fin))!=EOF) {
X if (c==SDELIM) VOID putc(SDELIM,fout); /*double up SDELIM*/
X VOID putc(c,fout);
X }
X VOID putc(SDELIM,fout); VOID putc('\n',fout);
X VOID fclose(fin);
X return true;
X}
X
X
X
X#ifdef SYNTEST
X
Xmain(argc,argv)
Xint argc; char * argv[];
X{
X
X cmdid = "syntest";
X if (argc<2) {
X VOID fputs("No input file\n",stderr);
X exit(-1);
X }
X if ((finptr=fopen(argv[1], "r")) == NULL) {
X faterror("Can't open input file %s\n",argv[1]);
X }
X Lexinit();
X getadmin();
X putadmin(stdout);
X
X gettree();
X puttree(Head,stdout);
X
X getdesc(true);
X
X if (nextlex(),nexttok!=EOFILE) {
X fatserror("Syntax error");
X }
X exit(0);
X}
X
X
Xcleanup(){}
X/*dummy*/
X
X
X#endif
X
X@
X
X
X4.6.2.1
Xlog
X@Start of Amiga RCS port branch.
X@
Xtext
X@d5 1
Xa5 5
X<<<<<<< rcssyn.c
Xstatic char rcsid[]= "$Id: rcssyn.c,v 4.6.1.1 89/08/11 01:43:06 rsbx Exp Locker: rsbx $ Purdue CS";
X=======
Xstatic char rcsid[]= "$Id: rcssyn.c,v 1.2 89/09/17 13:36:37 rick Exp $ Purdue CS";
X>>>>>>> 1.2
Xa41 16
X<<<<<<< rcssyn.c
X * Revision 4.6.1.1 89/08/11 01:43:06 rsbx
X * Start of cbmvax RCS source branch.
X *
X * Revision 4.6 89/05/01 15:13:32 narten
X * checked in with -k by rsbx at 89.08.10.16.23.06.
X=======
X * Revision 1.2 89/09/17 13:36:37 rick
X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
X * All changes done with conditional compile (#ifdef AMIGA). This version
X * compiles correctly with Lattice C version 5.02 or later.
X *
X * Revision 1.2 88/09/03 15:12:39 rick
X * Port to AmigaDos. All done with conditional compiles
X>>>>>>> 1.2
X *
X@
X
X
X4.6.2.2
Xlog
X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
Xsources I have here (and are later than the ones Rick used).
X@
Xtext
X@d5 5
Xa9 1
Xstatic char rcsid[]= "$Id: rcssyn.c,v 4.6.2.1 89/10/13 19:19:15 rsbx Exp Locker: rsbx $ Purdue CS";
Xd46 1
Xa46 3
X * Revision 4.6.2.1 89/10/13 19:19:15 rsbx
X * Start of Amiga RCS port branch.
X *
Xd52 9
X@
X
X
X4.6.1.1
Xlog
X@Start of cbmvax RCS source branch.
X@
Xtext
X@a42 3
X * checked in with -k by rsbx at 89.08.10.16.23.06.
X *
X * Revision 4.6 89/05/01 15:13:32 narten
X@
SHAR_EOF
echo "extracting rcs/rcs.rcsfiles/rcsutil.c,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcsutil.c,v
Xhead 4.6;
Xbranch 4.6.2;
Xaccess ;
Xsymbols amiga_rcs:4.6.2 cbmvax_source:4.6.1 uunet_june89_dist:4.6;
Xlocks ; strict;
Xcomment @ * @;
X
X
X4.6
Xdate 89.05.01.15.13.40; author narten; state Exp;
Xbranches 4.6.1.1 4.6.2.1;
Xnext ;
X
X4.6.1.1
Xdate 89.08.11.01.43.12; author rsbx; state Exp;
Xbranches ;
Xnext 4.6.1.2;
X
X4.6.1.2
Xdate 89.08.11.02.17.29; author rsbx; state Exp;
Xbranches ;
Xnext 4.6.1.3;
X
X4.6.1.3
Xdate 89.10.16.15.08.36; author rsbx; state Exp;
Xbranches ;
Xnext ;
X
X4.6.2.1
Xdate 89.10.13.19.19.20; author rsbx; state Exp;
Xbranches ;
Xnext 4.6.2.2;
X
X4.6.2.2
Xdate 89.10.15.15.45.09; author rsbx; state Exp;
Xbranches ;
Xnext 4.6.2.3;
X
X4.6.2.3
Xdate 89.10.15.18.27.58; author rsbx; state Exp;
Xbranches ;
Xnext 4.6.2.4;
X
X4.6.2.4
Xdate 89.10.16.19.01.15; author rsbx; state Exp;
Xbranches ;
Xnext 4.6.2.5;
X
X4.6.2.5
Xdate 89.10.16.19.07.28; author rsbx; state Exp;
Xbranches ;
Xnext 4.6.2.6;
X
X4.6.2.6
Xdate 89.10.16.23.54.57; author rsbx; state Exp;
Xbranches ;
Xnext 4.6.2.7;
X
X4.6.2.7
Xdate 89.10.17.15.04.39; author rsbx; state Exp;
Xbranches ;
Xnext 4.6.2.8;
X
X4.6.2.8
Xdate 89.10.18.10.54.09; author rsbx; state Exp;
Xbranches ;
Xnext ;
X
X
Xdesc
X@RCS utilities.
X@
X
X
X4.6
Xlog
X@checked in with -k by rsbx at 89.08.10.16.23.16.
X@
Xtext
X@/*
X * RCS utilities
X */
X#ifndef lint
Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6 89/05/01 15:13:40 narten Exp $ Purdue CS";
X#endif
X
X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Walter Tichy.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X * Report all problems and direct all questions to:
X * rcs-bugs@@cs.purdue.edu
X *
X
X
X
X
X
X
X
X*/
X
X
X
X
X/* $Log: rcsutil.c,v $
X * Revision 4.6 89/05/01 15:13:40 narten
X * changed copyright header to reflect current distribution rules
X *
X * Revision 4.5 88/11/08 16:01:02 narten
X * corrected use of varargs routines
X *
X * Revision 4.4 88/11/08 12:00:28 narten
X * changes from eggert@@sm.unisys.com (Paul Eggert)
X *
X * Revision 4.4 88/08/09 19:13:24 eggert
X * Check for memory exhaustion.
X * Permit signal handlers to yield either 'void' or 'int'; fix oldSIGINT botch.
X * Use execv(), not system(); yield exit status like diff(1)'s.
X *
X * Revision 4.3 87/10/18 10:40:22 narten
X * Updating version numbers. Changes relative to 1.1 actually
X * relative to 4.1
X *
X * Revision 1.3 87/09/24 14:01:01 narten
X * Sources now pass through lint (if you ignore printf/sprintf/fprintf
X * warnings)
X *
X * Revision 1.2 87/03/27 14:22:43 jenkins
X * Port to suns
X *
X * Revision 1.1 84/01/23 14:50:43 kcs
X * Initial revision
X *
X * Revision 4.1 83/05/10 15:53:13 wft
X * Added getcaller() and findlock().
X * Changed catchints() to check SIGINT for SIG_IGN before setting up the signal
X * (needed for background jobs in older shells). Added restoreints().
X * Removed printing of full RCS path from logcommand().
X *
X * Revision 3.8 83/02/15 15:41:49 wft
X * Added routine fastcopy() to copy remainder of a file in blocks.
X *
X * Revision 3.7 82/12/24 15:25:19 wft
X * added catchints(), ignoreints() for catching and ingnoring interrupts;
X * fixed catchsig().
X *
X * Revision 3.6 82/12/08 21:52:05 wft
X * Using DATEFORM to format dates.
X *
X * Revision 3.5 82/12/04 18:20:49 wft
X * Replaced SNOOPDIR with SNOOPFILE; changed addlock() to update
X * lockedby-field.
X *
X * Revision 3.4 82/12/03 17:17:43 wft
X * Added check to addlock() ensuring only one lock per person.
X * Addlock also returns a pointer to the lock created. Deleted fancydate().
X *
X * Revision 3.3 82/11/27 12:24:37 wft
X * moved rmsema(), trysema(), trydiraccess(), getfullRCSname() to rcsfnms.c.
X * Introduced macro SNOOP so that snoop can be placed in directory other than
X * TARGETDIR. Changed %02d to %.2d for compatibility reasons.
X *
X * Revision 3.2 82/10/18 21:15:11 wft
X * added function getfullRCSname().
X *
X * Revision 3.1 82/10/13 16:17:37 wft
X * Cleanup message is now suppressed in quiet mode.
X */
X
X
X
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <signal.h>
X#include "rcsbase.h"
X#include <pwd.h>
X#include <varargs.h>
X
X#if defined(USG) || defined(V4_2BSD)
X#include <fcntl.h>
X#endif
X
X#ifndef V4_2BSD
X#define vfork fork
X#endif
X
Xextern char * bindex();
Xextern FILE * finptr;
Xextern char * RCSfilename;
Xextern char * getlogin();
Xextern struct passwd *getpwuid();
Xextern char * malloc();
X
X
Xchar * talloc(size)
Xunsigned size;
X{
X char * p;
X if (!(p = malloc(size))) {
X faterror("out of memory");
X }
X return p;
X}
X
X
X
Xchar * getcaller()
X/* Function: gets the callers login from his uid.
X * If the uid is root, tries to get the true login with getlogin().
X */
X{ char * name;
X int uid;
X uid=getuid();
X if (uid==0) {
X /* super user; try getlogin() to distinguish */
X name = getlogin();
X if (name!=nil && *name!='\0')
X return name;
X }
X return(getpwuid(uid)->pw_name);
X}
X
X
X
Xstruct hshentry * findlock(who,delete)
Xchar * who; int delete;
X/* Finds the first lock held by who and returns a pointer
X * to the locked delta; also removes the lock if delete==true.
X * Returns nil if there is no lock held by who.
X */
X{
X register struct lock * next, * trail;
X struct lock dummy;
X
X dummy.nextlock=next=Locks;
X trail = &dummy;
X while (next!=nil) {
X if(strcmp(who,next->login)==0) break; /*found a lock*/
X trail=next;
X next=next->nextlock;
X }
X if (next!=nil) {
X /* found one */
X if (delete) {
X /* delete it */
X trail->nextlock=next->nextlock;
X Locks=dummy.nextlock;
X next->delta->lockedby=nil; /* reset locked-by */
X }
X return next->delta;
X } else return nil;
X}
X
X
X
X
X
X
X
Xstruct lock * addlock(delta,who)
Xstruct hshentry * delta; char * who;
X/* Given a delta, addlock checks whether
X * the delta is locked by somebody other than who.
X * If so, an error message is printed, and false returned.
X * If the delta is not reserved at all, a lock for it is added,
X * and a pointer for the lock returned.
X */
X{
X struct lock * next;
X
X next=Locks;
X while (next!=nil) {
X if (cmpnum(delta->num,next->delta->num)==0) {
X if (strcmp(who,next->login)==0)
X return next;
X /* lock exists already */
X else {
X error("revision %s already locked by %s",
X delta->num, next->login);
X return false;
X }
X } else {
X if (strcmp(who,next->login)==0) {
X error("you already locked %s; only one lock allowed per person.",
X next->delta->num);
X return false;
X } else {
X next=next->nextlock;
X }
X }
X }
X /* not found; set up new lockblock */
X next= (struct lock *) talloc(sizeof (struct lock));
X delta->lockedby=next->login=who;
X next->delta= delta;
X next->nextlock=Locks;
X Locks=next;
X return next;
X}
X
X
X
Xint addsymbol(delta,name,rebind)
Xstruct hshentry * delta; char * name; int rebind;
X/* Function: adds a new symbolic name and associates it with node delta.
X * If name already exists and rebind is true, the name is associated
X * with the new delta; otherwise, an error message is printed and
X * false returned. Returns true it successful.
X */
X{ register struct assoc * next;
X next=Symbols;
X while (next!=nil) {
X if (strcmp(name,next->symbol)==0) {
X if (rebind) {
X next->delta=delta;
X return true;
X } else {
X error("symbolic name %s already bound to %s",
X name,next->delta->num);
X return false;
X }
X } else next = next->nextassoc;
X }
X /* not found; insert new pair. */
X next = (struct assoc *) talloc(sizeof(struct assoc));
X next->symbol=name;
X next->delta=delta;
X next->nextassoc=Symbols;
X Symbols = next;
X return true;
X}
X
X
X
X
Xint checkaccesslist(who)
Xchar * who;
X/* function: Returns true if who is the superuser, the owner of the
X * file, the access list is empty, or who is on the access list.
X * Prints an error message and returns false otherwise.
X */
X{
X register struct access * next;
X struct stat statbuf;
X
X if ((AccessList==nil) || (strcmp(who,"root")==0))
X return true;
X
X next=AccessList;
X do {
X if (strcmp(who,next->login)==0)
X return true;
X next=next->nextaccess;
X } while (next!=nil);
X
X VOID fstat(fileno(finptr),&statbuf); /* get owner of file */
X if (getuid() == statbuf.st_uid) return true;
X
X error("User %s not on the access list",who);
X return false;
X}
X
X
Xstatic SIGNAL_TYPE catchsig(s)
X{
X ignoreints();
X diagnose("\nRCS: cleaning up\n");
X VOID cleanup();
X exit(2);
X#ifdef lint
X catchsig(s);
X#endif
X}
X
Xstatic sig[] = {SIGINT,SIGHUP,SIGQUIT,SIGPIPE,SIGTERM};
X#define SIGS (sizeof(sig)/sizeof(*sig))
Xstatic SIGNAL_TYPE (*catcher[SIGS])();
X
X void catchints()
X {
X register i;
X for (i=SIGS; 0<=--i; )
X catcher[i] =
X signal(sig[i],SIG_IGN) == SIG_IGN ? SIG_IGN : catchsig;
X restoreints();
X }
X
X void ignoreints()
X {
X register i;
X for (i=SIGS; 0<=--i; )
X VOID signal(sig[i], SIG_IGN);
X }
X
Xvoid restoreints()
X{
X register i;
X for (i=SIGS; 0<=--i; )
X if (catcher[i] != SIG_IGN)
X VOID signal(sig[i], catcher[i]);
X}
X
Xfastcopy(inf,outf)
XFILE * inf, * outf;
X/* Function: copies the remainder of file inf to outf. First copies the
X * rest that is in the IO-buffer of inf character by character, and then
X * copies the remainder in blocks.
X */
X{ char buf[BUFSIZ];
X register int rcount, wcount;
X
X /* write the rest of the buffer to outf */
X while ((--inf->_cnt)>=0) {
X VOID putc(*inf->_ptr++&0377,outf);
X }
X if (fflush(outf) == EOF) {
X writeerror();
X }
X
X /*now read the rest of the file in blocks*/
X while ((rcount=read(fileno(inf),buf,BUFSIZ))>0) {
X wcount=write(fileno(outf),buf,rcount);
X if (wcount!=rcount) {
X writeerror();
X }
X }
X}
X
X
X
X
X
X
X#ifdef SNOOPFILE
X
X#include "time.h"
Xextern struct tm* localtime();
Xextern long time();
X
Xlogcommand(commandname,delta, sequence,login)
Xchar* commandname; struct hshentry * delta, * sequence[];char * login;
X/* Function: start a process to write the file that
X * logs the RCS command.
X * Each line in the log file contains the following information:
X * operation, revision(r), backward deltas applied(b), forward deltas applied(f),
X * total deltas present(t), creation date of delta(d), date of operation(o),
X * login of caller, RCS file name.
X */
X{
X char logline[200];
X char curdate[datelength];
X char *inoutargs[5];
X register int i, backward, forward;
X long clock;
X struct tm * tm;
X
X clock=time((long *)0);
X tm=localtime(&clock);
X
X VOID sprintf(curdate,DATEFORM,
X tm->tm_year, tm->tm_mon+1, tm->tm_mday,
X tm->tm_hour, tm->tm_min, tm->tm_sec);
X
X i= backward=forward=0;
X while(sequence[i]!=nil) { /* count deltas to be applied*/
X if (countnumflds(sequence[i]->num) == 2)
X backward++; /* reverse delta */
X else forward++; /* branch delta */
X i++;
X }
X VOID sprintf(logline,"%s %10sr %3db %3df %3dt %sc %so %s %s",
X commandname,delta->num,backward,forward,TotalDeltas,delta->date,
X curdate,login,bindex(getfullRCSname(),'/'));
X inoutargs[0] = nil;
X inoutargs[1] = nil;
X inoutargs[2] = SNOOP;
X inoutargs[3] = logline;
X inoutargs[4] = nil;
X VOID run_back(inoutargs);
X}
X#endif
X
X
Xstatic int fdreopen(fd, file, flags, mode)
X char *file;
X{
X int newfd;
X VOID close(fd);
X newfd = flags==-1 ? creat(file,mode) : open(file,flags,mode);
X if (newfd < 0 || newfd == fd)
X return newfd;
X#ifdef F_DUPFD
X fd = fcntl(newfd, F_DUPFD, fd);
X#else
X fd = dup2(newfd, fd);
X#endif
X VOID close(newfd);
X return fd;
X}
X
Xstatic void tryopen(fd,file,flags)
X char *file;
X{
X if (file && fdreopen(fd,file,flags,0600) != fd) {
X VOID write(fileno(stderr), file, strlen(file));
X VOID write(fileno(stderr), ": cannot open\n", 14);
X _exit(2);
X }
X}
X
X/*
X/* Run in the background a command specified by the strings in 'inoutargs'.
X/* inoutargs[0], if nonnil, is the name of the input file.
X/* inoutargs[1], if nonnil, is the name of the output file.
X/* inoutargs[2..] form the command to be run in the background.
X/*/
Xstatic int run_back(inoutargs)
X register char **inoutargs;
X{
X int pid;
X if (fflush(stdout) == EOF || fflush(stderr) == EOF)
X return -1;
X if (!(pid = vfork())) {
X tryopen(fileno(stdin), inoutargs[0], 0);
X tryopen(fileno(stdout), inoutargs[1], -1);
X VOID execv(inoutargs[2], &inoutargs[2]);
X inoutargs[1] = "/bin/sh";
X VOID execv(inoutargs[1], &inoutargs[1]);
X VOID write(fileno(stderr), "/bin/sh: not found\n", 19);
X _exit(2);
X }
X return pid;
X}
X
X#define CARGSMAX 20
X/*
X/* Run a command.
X/* The first two arguments are the input and output files (if nonnil);
X/* the rest specify the command and its arguments.
X/*/
Xint run(va_alist)
X va_dcl
X{
X va_list ap;
X int pid, wstatus, w;
X char *rgargs[CARGSMAX];
X register i = 0;
X va_start(ap);
X rgargs[0] = va_arg(ap, char *);
X rgargs[1] = va_arg(ap, char *);
X for (i =2; i< CARGSMAX; i++) {
X rgargs[i] = va_arg(ap, char *);
X if (rgargs[i] == NULL)
X break;
X }
X va_end(ap);
X pid = run_back(rgargs);
X if (pid < 0)
X return pid;
X for (;;)
X if ((w = wait(&wstatus)) < 0)
X return w;
X else if (w == pid)
X return wstatus;
X}
X@
X
X
X4.6.2.1
Xlog
X@Start of Amiga RCS port branch.
X@
Xtext
X@d5 1
Xa5 5
X<<<<<<< rcsutil.c
Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.1.2 89/08/11 02:17:29 rsbx Exp Locker: rsbx $ Purdue CS";
X=======
Xstatic char rcsid[]= "$Id: rcsutil.c,v 1.2 89/09/17 13:36:49 rick Exp $ Purdue CS";
X>>>>>>> 1.2
Xa36 14
X<<<<<<< rcsutil.c
X * Revision 4.6.1.2 89/08/11 02:17:29 rsbx
X * Changed catchints() to compile on cbmvax.
X=======
X * Revision 1.2 89/09/17 13:36:49 rick
X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
X * All changes done with conditional compile (#ifdef AMIGA). This version
X * compiles correctly with Lattice C version 5.02 or later.
X>>>>>>> 1.2
X *
X<<<<<<< rcsutil.c
X * Revision 4.6.1.1 89/08/11 01:43:12 rsbx
X * Start of cbmvax RCS source branch.
X *
Xa37 3
X * checked in with -k by rsbx at 89.08.10.16.23.16.
X *
X * Revision 4.6 89/05/01 15:13:40 narten
Xa50 11
X=======
X * Revision 1.4 89/09/16 09:43:48 rick
X * Modified AMIGA changes to work with Lattice C
X *
X * Revision 1.3 88/09/03 17:16:22 rick
X * Make fastcopy really fast for AmigaDos
X *
X * Revision 1.2 88/09/03 15:12:57 rick
X * Port to AmigaDos. All done with conditional compiles
X *
X>>>>>>> 1.2
Xd103 1
Xa103 1
X#ifndef AMIGA
Xd107 1
Xa108 1
X<<<<<<< rcsutil.c
Xa113 7
X=======
X#else
X#include "stat.h"
X#include <signal.h>
X#endif
X#include "rcsbase.h"
X>>>>>>> 1.2
Xa125 8
X<<<<<<< rcsutil.c
X=======
X#ifdef AMIGA
Xshort oldSIGINT;
X#else
Xint (*oldSIGINT)(); /* saves the original value for SIGINT */
X#endif
X>>>>>>> 1.2
Xa126 1
X<<<<<<< rcsutil.c
Xa135 6
X=======
X#ifdef AMIGA
Xchar *getcaller()
X{
X char *getenv();
X>>>>>>> 1.2
Xa136 1
X<<<<<<< rcsutil.c
Xa138 5
X=======
X return(getenv("LOGNAME"));
X}
X#else
X>>>>>>> 1.2
Xa153 1
X#endif
Xd156 1
Xa287 3
X#ifdef AMIGA
X return true;
X#else
Xa292 1
X#endif
Xa294 1
X<<<<<<< rcsutil.c
Xa298 31
X=======
X#ifdef AMIGA
X
Xcatchsig()
X{
X diagnose("\nRCS: cleaning up\n");
X VOID cleanup();
X exit(1);
X}
X
Xvoid catchints()
X{
X signal(SIGINT,catchsig);
X}
X
Xvoid ignoreints()
X{
X signal(SIGINT,SIG_IGN);
X}
X
Xvoid restoreints()
X{
X signal(SIGINT,catchsig);
X}
X
X#else
X
Xcatchsig(sig)
X{
X VOID signal(sig, SIG_IGN);
X>>>>>>> 1.2
Xd315 2
Xa316 4
X if (signal(sig[i],SIG_IGN) == SIG_IGN)
X catcher[i] = SIG_IGN;
X else
X catcher[i] = catchsig;
Xa333 1
X#endif
Xa334 1
X<<<<<<< rcsutil.c
Xa335 27
X=======
X#ifdef AMIGA
X#define AMIGABUF (4 *1024)
Xfastcopy(inf,outf)
XFILE *inf,*outf;
X{
X static char buf[AMIGABUF];
X register int rcount, wcount;
X int infd,outfd;
X
X while (inf->_rcnt--)
X putc(*inf->_ptr++,outf);
X fflush(outf);
X infd = fileno(inf);
X outfd = fileno(outf);
X
X while ((rcount = read(infd,buf,AMIGABUF)) > 0) {
X if (rcount) {
X wcount = write(outfd,buf,rcount);
X if (wcount!=rcount)
X faterror("write error");
X }
X }
X}
X#else
Xfastcopy(inf,outf)
X>>>>>>> 1.2
Xa359 4
X<<<<<<< rcsutil.c
X=======
X#endif
X>>>>>>> 1.2
X@
X
X
X4.6.2.2
Xlog
X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
Xsources I have here (and are later than the ones Rick used).
X@
Xtext
X@d5 5
Xa9 1
Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.2.1 89/10/13 19:19:20 rsbx Exp Locker: rsbx $ Purdue CS";
Xd41 1
Xa41 3
X * Revision 4.6.2.1 89/10/13 19:19:20 rsbx
X * Start of Amiga RCS port branch.
X *
Xd44 6
Xd51 1
Xd72 11
Xd140 2
Xd146 1
Xa146 1
X
Xa150 1
X
Xd152 1
Xa153 6
X#ifdef STDARGS
X#include <stdarg.h>
X#else
X#include <varargs.h>
X#endif
X
Xd165 2
Xd168 1
Xa168 2
Xextern int run_back(char **inoutargs);
X/* short oldSIGINT; */
Xd172 1
Xd174 1
Xd184 1
Xa184 2
X
X
Xd189 6
Xd198 1
Xa335 1
X#ifndef AMIGA
Xd337 1
Xa337 1
X#endif
Xd359 6
Xd367 1
Xa367 1
Xstatic SIGNAL_TYPE catchsig()
Xd391 1
Xa391 1
Xstatic SIGNAL_TYPE catchsig(s)
Xd393 2
Xa394 1
X ignoreints();
Xd407 1
Xa407 1
Xvoid catchints()
Xd418 1
Xa418 1
Xvoid ignoreints()
Xd434 3
Xd462 1
Xd487 2
Xd490 1
Xd546 1
Xa546 1
X#ifndef AMIGA
Xa596 1
X#endif
Xa598 1
X#ifdef STDARGS
Xd600 4
Xa603 34
X * Run a command.
X * The first two arguments are the input and output files (if nonnil);
X * the rest specify the command and its arguments.
X */
Xint run(char *arg0, char *arg1, ...)
X{
X va_list ap;
X int pid, wstatus, w;
X char *rgargs[CARGSMAX];
X register i;
X va_start(ap, arg1);
X rgargs[0] = arg0;
X rgargs[1] = arg1;
X for (i =2; i< CARGSMAX; i++) {
X rgargs[i] = va_arg(ap, char *);
X if (rgargs[i] == NULL)
X break;
X }
X va_end(ap);
X pid = run_back(rgargs);
X if (pid < 0)
X return pid;
X for (;;)
X if ((w = wait(&wstatus)) < 0)
X return w;
X else if (w == pid)
X return wstatus;
X}
X#else
X/*
X * Run a command.
X * The first two arguments are the input and output files (if nonnil);
X * the rest specify the command and its arguments.
X */
Xa628 1
X#endif
X@
X
X
X4.6.2.3
Xlog
X@More changes to make Amiga port work.
X@
Xtext
X@d5 1
Xa5 1
Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.2.2 89/10/15 15:45:09 rsbx Exp $ Purdue CS";
Xa36 4
X * Revision 4.6.2.2 89/10/15 15:45:09 rsbx
X * Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
X * sources I have here (and are later than the ones Rick used).
X *
Xa167 2
Xchar *getenv();
Xstatic char *unknownname = "Unknown";
Xd170 2
Xa171 8
X char *name;
X name = getenv("LOGNAME");
X
X if ((name == NULL) || (*name == '\0'))
X {
X return unknownname;
X }
X return name;
X@
X
X
X4.6.2.4
Xlog
X@run() moved from rcsutil.c to amiga.c and made to work.
X@
Xtext
X@d5 1
Xa5 1
Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.1.3 89/10/16 15:08:36 rsbx Exp $ Purdue CS";
Xa36 3
X * Revision 4.6.2.3 89/10/15 18:27:58 rsbx
X * More changes to make Amiga port work.
X *
Xd153 6
Xd571 1
Xa634 1
X#endif
X@
X
X
X4.6.2.5
Xlog
X@Changed file path handling to deal with Amiga file path sematics.
X@
Xtext
X@a36 3
X * Revision 4.6.1.3 89/10/16 15:08:36 rsbx
X * run() move from rcsutil.c to amiga.c and made to work.
X *
Xd122 1
Xa122 4
X#ifdef AMIGA
X#include "stat.h"
X#include <signal.h>
X#else
Xd132 3
Xd149 1
Xd430 3
Xa432 3
X if (wcount!=rcount)
X faterror("write error");
X }
Xd507 1
Xa507 1
X curdate,login,fnamepart(getfullRCSname()));
X@
X
X
X4.6.2.6
Xlog
X@Changes to getcaller().
X@
Xtext
X@d5 1
Xa5 1
Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.2.5 89/10/16 19:07:28 rsbx Exp $ Purdue CS";
Xa36 3
X * Revision 4.6.2.5 89/10/16 19:07:28 rsbx
X * Changed file path handling to deal with Amiga file path sematics.
X *
Xa140 1
X#include <ctype.h>
Xd176 1
Xa176 2
X char *sp;
X char c;
Xd178 3
Xa180 18
X sp = name = getenv("LOGNAME");
X
X#ifdef TODO
X/* check for ethernet user/hostname */
X#endif
X
X if (sp) {
X while ((c = *sp) && (isascii(c))) {
X switch (ctab[c]) {
X case IDCHAR:
X case LETTER:
X case DIGIT:
X sp++;
X continue;
X default:
X *sp = '\0';
X break;
X }
Xa181 5
X }
X
X if ((name == NULL) || (*name == '\0')) {
X return unknownname;
X }
X@
X
X
X4.6.2.7
Xlog
X@Yet more changes to getcaller().
X@
Xtext
X@d5 1
Xa5 1
Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.2.6 89/10/16 23:54:57 rsbx Exp $ Purdue CS";
Xa36 3
X * Revision 4.6.2.6 89/10/16 23:54:57 rsbx
X * Changes to getcaller().
X *
Xd183 1
Xa183 3
X if (!(name = getenv("LOGNAME"))) {
X return unknownname;
X }
Xd188 13
Xa200 11
X sp =name;
X while ((c = *sp) && (isascii(c))) {
X switch (ctab[c]) {
X case IDCHAR:
X case LETTER:
X case DIGIT:
X sp++;
X continue;
X default:
X *sp = '\0';
X break;
Xd204 1
Xa204 3
X
X if (*name == '\0') {
X free(name);
Xd207 1
Xa207 5
X
X sp = talloc(sp-name+1);
X strcpy(sp, name);
X free(name);
X return sp;
X@
X
X
X4.6.2.8
Xlog
X@LOGNAME changed to USERNAME. Still need to check the Ameristar software
Xfor username.
X@
Xtext
X@d5 1
Xa5 1
Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.2.7 89/10/17 15:04:39 rsbx Exp $ Purdue CS";
Xa36 3
X * Revision 4.6.2.7 89/10/17 15:04:39 rsbx
X * Yet more changes to getcaller().
X *
Xd186 1
Xa186 1
X if (!(name = getenv("USERNAME"))) {
X@
X
X
X4.6.1.1
Xlog
X@Start of cbmvax RCS source branch.
X@
Xtext
X@a37 3
X * checked in with -k by rsbx at 89.08.10.16.23.16.
X *
X * Revision 4.6 89/05/01 15:13:40 narten
X@
X
X
X4.6.1.2
Xlog
X@Changed catchints() to compile on cbmvax.
X@
Xtext
X@d5 1
Xa5 1
Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.1.1 89/08/11 01:43:12 rsbx Exp Locker: rsbx $ Purdue CS";
Xa36 3
X * Revision 4.6.1.1 89/08/11 01:43:12 rsbx
X * Start of cbmvax RCS source branch.
X *
Xd318 2
Xa319 4
X if (signal(sig[i],SIG_IGN) == SIG_IGN)
X catcher[i] = SIG_IGN;
X else
X catcher[i] = catchsig;
X@
X
X
X4.6.1.3
Xlog
X@run() move from rcsutil.c to amiga.c and made to work.
X@
Xtext
X@d5 1
Xa5 1
Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.2.3 89/10/15 18:27:58 rsbx Exp $ Purdue CS";
Xa36 13
X * Revision 4.6.2.3 89/10/15 18:27:58 rsbx
X * More changes to make Amiga port work.
X *
X * Revision 4.6.2.2 89/10/15 15:45:09 rsbx
X * Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
X * sources I have here (and are later than the ones Rick used).
X *
X * Revision 4.6.2.1 89/10/13 19:19:20 rsbx
X * Start of Amiga RCS port branch.
X *
X * Revision 4.6.1.2 89/08/11 02:17:29 rsbx
X * Changed catchints() to compile on cbmvax.
X *
Xd109 1
Xa109 1
X#ifndef AMIGA
Xd113 1
Xd115 1
Xa120 13
X#else
X#include "stat.h"
X#include <signal.h>
X#endif
X
X#include "rcsbase.h"
X
X#ifdef STDARGS
X#include <stdarg.h>
X#else
X#include <varargs.h>
X#endif
X
Xa143 7
X#ifdef AMIGA
Xchar *getenv();
Xstatic char *unknownname = "Unknown";
Xchar *getcaller()
X{
X char *name;
X name = getenv("LOGNAME");
Xa144 7
X if ((name == NULL) || (*name == '\0'))
X {
X return unknownname;
X }
X return name;
X}
X#else
Xa159 1
X#endif
Xd162 1
Xa281 1
X#ifndef AMIGA
Xd283 1
Xa283 1
X#endif
Xa293 3
X#ifdef AMIGA
X return true;
X#else
Xa298 1
X#endif
Xa300 1
X#ifdef AMIGA
Xa301 24
Xstatic SIGNAL_TYPE catchsig()
X{
X diagnose("\nRCS: cleaning up\n");
X VOID cleanup();
X exit(1);
X}
X
Xvoid catchints()
X{
X signal(SIGINT,catchsig);
X}
X
Xvoid ignoreints()
X{
X signal(SIGINT,SIG_IGN);
X}
X
Xvoid restoreints()
X{
X signal(SIGINT,catchsig);
X}
X
X#else
X
Xd317 1
Xa317 1
Xvoid catchints()
Xd328 1
Xa328 1
Xvoid ignoreints()
Xa341 1
X#endif
Xa342 2
X#ifdef AMIGA
X#define AMIGABUF (4 *1024)
Xa343 22
XFILE *inf,*outf;
X{
X static char buf[AMIGABUF];
X register int rcount, wcount;
X int infd,outfd;
X
X while (inf->_rcnt--)
X putc(*inf->_ptr++,outf);
X fflush(outf);
X infd = fileno(inf);
X outfd = fileno(outf);
X
X while ((rcount = read(infd,buf,AMIGABUF)) > 0) {
X if (rcount) {
X wcount = write(outfd,buf,rcount);
X if (wcount!=rcount)
X faterror("write error");
X }
X }
X}
X#else
Xfastcopy(inf,outf)
Xa367 1
X#endif
Xd423 1
Xa423 1
X#ifndef AMIGA
Xa475 1
X#ifdef STDARGS
Xd477 4
Xa480 34
X * Run a command.
X * The first two arguments are the input and output files (if nonnil);
X * the rest specify the command and its arguments.
X */
Xint run(char *arg0, char *arg1, ...)
X{
X va_list ap;
X int pid, wstatus, w;
X char *rgargs[CARGSMAX];
X register i;
X va_start(ap, arg1);
X rgargs[0] = arg0;
X rgargs[1] = arg1;
X for (i =2; i< CARGSMAX; i++) {
X rgargs[i] = va_arg(ap, char *);
X if (rgargs[i] == NULL)
X break;
X }
X va_end(ap);
X pid = run_back(rgargs);
X if (pid < 0)
X return pid;
X for (;;)
X if ((w = wait(&wstatus)) < 0)
X return w;
X else if (w == pid)
X return wstatus;
X}
X#else
X/*
X * Run a command.
X * The first two arguments are the input and output files (if nonnil);
X * the rest specify the command and its arguments.
X */
Xa505 2
X#endif
X#endif
X@
SHAR_EOF
echo "extracting rcs/rcs.rcsfiles/rlog.c,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rlog.c,v
Xhead 4.7;
Xbranch 4.7.2;
Xaccess ;
Xsymbols amiga_rcs:4.7.2 cbmvax_source:4.7.1 uunet_june89_dist:4.7;
Xlocks ; strict;
Xcomment @ * @;
X
X
X4.7
Xdate 89.05.01.15.13.48; author narten; state Exp;
Xbranches 4.7.1.1 4.7.2.1;
Xnext ;
X
X4.7.1.1
Xdate 89.08.11.01.43.14; author rsbx; state Exp;
Xbranches ;
Xnext ;
X
X4.7.2.1
Xdate 89.10.13.19.19.26; author rsbx; state Exp;
Xbranches ;
Xnext 4.7.2.2;
X
X4.7.2.2
Xdate 89.10.15.15.45.14; author rsbx; state Exp;
Xbranches ;
Xnext ;
X
X
Xdesc
X@RLOG operation.
X@
X
X
X
X4.7
Xlog
X@checked in with -k by rsbx at 89.08.10.16.23.28.
X@
Xtext
X@/*
X * RLOG operation
X */
X#ifndef lint
Xstatic char rcsid[]=
X"$Header: /usr/src/local/bin/rcs/src/RCS/rlog.c,v 4.7 89/05/01 15:13:48 narten Exp $ Purdue CS";
X#endif
X/*****************************************************************************
X * print contents of RCS files
X *****************************************************************************
X */
X
X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Walter Tichy.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X * Report all problems and direct all questions to:
X * rcs-bugs@@cs.purdue.edu
X *
X
X
X
X
X
X
X
X*/
X
X
X
X
X/* $Log: rlog.c,v $
X * Revision 4.7 89/05/01 15:13:48 narten
X * changed copyright header to reflect current distribution rules
X *
X * Revision 4.6 88/11/08 11:59:40 narten
X * changes from eggert@@sm.unisys.com (Paul Eggert)
X *
X * Revision 4.6 88/08/09 19:13:28 eggert
X * Check for memory exhaustion; don't access freed storage.
X * Shrink stdio code size; remove lint.
X *
X * Revision 4.5 87/12/18 11:46:38 narten
X * more lint cleanups (Guy Harris)
X *
X * Revision 4.4 87/10/18 10:41:12 narten
X * Updating version numbers
X * Changes relative to 1.1 actually relative to 4.2
X *
X * Revision 1.3 87/09/24 14:01:10 narten
X * Sources now pass through lint (if you ignore printf/sprintf/fprintf
X * warnings)
X *
X * Revision 1.2 87/03/27 14:22:45 jenkins
X * Port to suns
X *
X * Revision 1.1 84/01/23 14:50:45 kcs
X * Initial revision
X *
X * Revision 4.2 83/12/05 09:18:09 wft
X * changed rewriteflag to external.
X *
X * Revision 4.1 83/05/11 16:16:55 wft
X * Added -b, updated getnumericrev() accordingly.
X * Replaced getpwuid() with getcaller().
X *
X * Revision 3.7 83/05/11 14:24:13 wft
X * Added options -L and -R;
X * Fixed selection bug with -l on multiple files.
X * Fixed error on dates of the form -d'>date' (rewrote getdatepair()).
X *
X * Revision 3.6 82/12/24 15:57:53 wft
X * shortened output format.
X *
X * Revision 3.5 82/12/08 21:45:26 wft
X * removed call to checkaccesslist(); used DATEFORM to format all dates;
X * removed unused variables.
X *
X * Revision 3.4 82/12/04 13:26:25 wft
X * Replaced getdelta() with gettree(); removed updating of field lockedby.
X *
X * Revision 3.3 82/12/03 14:08:20 wft
X * Replaced getlogin with getpwuid(), %02d with %.2d, fancydate with PRINTDATE.
X * Fixed printing of nil, removed printing of Suffix,
X * added shortcut if no revisions are printed, disambiguated struct members.
X *
X * Revision 3.2 82/10/18 21:09:06 wft
X * call to curdir replaced with getfullRCSname(),
X * fixed call to getlogin(), cosmetic changes on output,
X * changed conflicting long identifiers.
X *
X * Revision 3.1 82/10/13 16:07:56 wft
X * fixed type of variables receiving from getc() (char -> int).
X */
X
X
X
X#include "time.h"
X#include "rcsbase.h"
X#ifndef lint
Xstatic char rcsbaseid[] = RCSBASE;
X#endif
X
Xextern char * partialno();
Xextern char * getcaller(); /*get login of caller */
Xextern free();
Xextern int countnumflds();
Xextern int compartial();
Xextern int expandsym(); /*get numeric name of a revision */
Xextern int nextc; /*next input character */
Xextern char Klog[];
Xextern char Ktext[];
Xextern int partime();
Xextern long maketime(); /*convert parsed time to unix time. */
Xextern struct tm * localtime(); /*convert unixtime into a tm-structure */
Xextern int pairfilenames();
Xextern struct hshentry * getnum();
Xextern FILE * finptr; /* RCS input file */
Xextern FILE * frewrite; /* new RCS file */
Xextern int rewriteflag; /* indicates whether input should be */
X /* echoed to frewrite */
Xextern int nerror; /* error counter */
X
Xchar * RCSfilename, * workfilename;
X
Xchar * caller; /* caller's login; */
Xint descflag, selectflag, selectop; /* option to print access list, symbolic */
X /* names, descriptive text, locks and */
X /* Head */
Xint onlylockflag; /* option to print only files */
X /* with locks */
Xint onlyRCSflag; /* option to print only RCS file name */
Xint lockflag; /* whether locker option is set */
Xint revno; /* number of revision chosen */
X
Xstruct lockers { /* lockers in locker option; stored */
X char * login; /* lockerlist */
X struct lockers * lockerlink;
X } ;
X
Xstruct stateattri { /* states in state option; stored in */
X char * status; /* statelist */
X struct stateattri * nextstate;
X } ;
X
Xstruct authors { /* login names in author option; */
X char * login; /* stored in authorlist */
X struct authors * nextauthor;
X } ;
X
Xstruct Revpairs{ /* revision or branch range in -r */
X int numfld; /* option; stored in revlist */
X char * strtrev;
X char * endrev;
X struct Revpairs * rnext;
X } ;
X
Xstruct Datepairs{ /* date range in -d option; stored in */
X char strtdate[datelength]; /* duelst and datelist */
X char enddate[datelength];
X struct Datepairs * dnext;
X };
X
Xchar Dotstring[200]; /* string of numeric revision name */
Xchar * Nextdotstring; /* next available place of Dotstring */
Xstruct Datepairs * datelist, * duelst;
Xstruct Revpairs * revlist, * Revlst;
Xint branchflag; /* set on -b */
Xstruct lockers * lockerlist;
Xstruct stateattri * statelist;
Xstruct authors * authorlist;
X
X
X
Xmain (argc, argv)
Xint argc;
Xchar * argv[];
X{
X struct Datepairs * currdate;
X struct assoc * curassoc;
X struct access * curaccess;
X struct lock * currlock;
X char * cmdusage;
X
X cmdusage = "command format:\nrlog -L -R -h -t -b -ddates -l[lockers] -rrevisions -sstates -w[logins] file ...";
X cmdid = "rlog";
X descflag = selectflag = true;
X lockflag = onlylockflag = selectop = false;
X onlyRCSflag = false;
X lockerlist = nil;
X authorlist = nil;
X statelist = nil;
X Revlst = revlist = nil;
X branchflag= false;
X duelst = datelist = nil;
X caller=getcaller();
X
X while (--argc,++argv, argc>=1 && ((*argv)[0] == '-')) {
X switch ((*argv)[1]) {
X
X case 'L':
X onlylockflag = true;
X break;
X
X case 'R':
X onlyRCSflag =true;
X break;
X
X case 'l':
X selectop = true;
X lockflag = true;
X getlocker( (*argv)+2 );
X break;
X
X case 'b':
X selectop = true;
X branchflag = true;
X break;
X
X case 'r':
X selectop = true;
X getrevpairs( (*argv)+2 );
X break;
X
X case 'd':
X selectop = true;
X getdatepair( (*argv)+2 );
X break;
X
X case 's':
X selectop = true;
X getstate( (*argv)+2);
X break;
X
X case 'w':
X selectop = true;
X getauthor( (*argv)+2);
X break;
X
X case 'h':
X if ( ! selectflag ) warn("option -t overrides -h");
X else descflag = false;
X break;
X
X case 't':
X selectflag = false;
X if ( ! descflag ) warn("option -t overrides -h");
X descflag = true;
X break;
X
X default:
X faterror("unknown option: %s\n%s", *argv,cmdusage);
X
X };
X } /* end of option processing */
X
X if (argc<1) faterror("No input file\n%s",cmdusage);
X
X
X /* now handle all filenames */
X do {
X rewriteflag=false;
X finptr=frewrite=nil;
X
X
X if (!pairfilenames(argc, argv, true,false)) continue;
X
X /* now RCSfilename contains the name of the RCS file, and finptr
X * the file descriptor. Workfilename contains the name of the
X * working file.
X */
X
X if ( !trysema(RCSfilename, false)) goto loopend; /* give up */
X
X /* do nothing if -L is given and there are no locks*/
X if ( onlylockflag && Locks == nil ) goto loopend;
X
X if ( onlyRCSflag ) {
X VOID fprintf(stdout, "%s\n", RCSfilename);
X goto loopend;
X }
X /* print RCS filename , working filename and optional
X administrative information */
X VOID fprintf(stdout, "\nRCS file: %s; ",RCSfilename);
X /* could use getfullRCSname() here, but that is very slow */
X VOID fprintf(stdout, "Working file: %s\n", workfilename);
X VOID fprintf(stdout, "head: %s\n", Head==nil?"":Head->num);
X VOID fprintf(stdout, "branch: %s\n", Dbranch==nil?"":Dbranch->num);
X
X VOID fputs("locks: ", stdout); /* print locker list */
X currlock = Locks;
X while( currlock ) {
X VOID fprintf(stdout," %s: %s;", currlock->login,
X currlock->delta->num);
X currlock = currlock->nextlock;
X }
X if ( StrictLocks )
X VOID fputs(Locks==nil?" ; strict":" strict",stdout);
X
X VOID fputs("\naccess list: ", stdout); /* print access list */
X curaccess = AccessList;
X while(curaccess) {
X VOID fputs(" ",stdout);
X VOID fputs(curaccess->login, stdout);
X curaccess = curaccess->nextaccess;
X }
X
X VOID fputs("\nsymbolic names:", stdout); /* print symbolic names */
X curassoc = Symbols;
X while( curassoc ) {
X VOID fprintf(stdout, " %s: %s;",curassoc->symbol,
X curassoc->delta->num);
X curassoc = curassoc->nextassoc;
X }
X
X VOID fprintf(stdout,"\ncomment leader: \"%s\"\n",Comment);
X
X gettree();
X VOID fprintf(stdout, "total revisions: %d; ", TotalDeltas);
X if ( Head == nil || !selectflag || !descflag) {
X VOID putc('\n',stdout);
X if (descflag) VOID fputs("description:\n", stdout);
X getdesc(descflag);
X VOID fputs("=============================================================================\n",stdout);
X goto loopend;
X }
X
X
X /* keep only those locks given by -l */
X if (lockflag)
X trunclocks();
X getnumericrev(); /* get numeric revision or branch names */
X revno = 0;
X
X exttree(Head);
X
X /* get most recently date of the dates pointed by duelst */
X currdate = duelst;
X while( currdate) {
X recentdate(Head, currdate);
X currdate = currdate->dnext;
X }
X
X extdate(Head);
X
X /* reinitialize the date specification list */
X currdate = duelst;
X while(currdate) {
X VOID sprintf(currdate->strtdate,DATEFORM,0,0,0,0,0,0);
X currdate = currdate->dnext;
X }
X
X if ( selectop || ( selectflag && descflag) )
X VOID fprintf(stdout, "selected revisions: %d", revno);
X VOID putc('\n', stdout);
X if (descflag) VOID fputs("description:\n", stdout);
X getdesc(descflag);
X while( (nexttok != EOFILE) && readdeltalog());
X if (selectflag && descflag && revno) {
X putrunk();
X putree(Head);
X if (nextlex(), nexttok != EOFILE)
X fatserror("syntax error; expecting EOF");
X }
X VOID fputs("=============================================================================\n",stdout);
X loopend:
X VOID fclose(finptr);
X } while( ++argv, --argc >= 1);
X exit(nerror!=0);
X}
X
X
X
Xputrunk()
X/* function: print revisions chosen, which are in trunk */
X
X{
X struct hshentry * ptr, * pre;
X
X if (Head == nil) return; /* empty tree */
X
X pre = Head;
X ptr = Head->next;
X while( ptr ) {
X putadelta(pre,ptr,true);
X pre = ptr;
X ptr = ptr->next;
X }
X putadelta(pre,ptr,true);
X}
X
X
X
Xputree(root)
Xstruct hshentry *root;
X/* function: print delta tree( not include trunck) in reversed calender
X order on each branch */
X
X{
X if ( root == nil ) return;
X
X putree(root->next);
X
X putforest(root->branches);
X}
X
X
X
X
Xputforest(branchroot)
Xstruct branchhead * branchroot;
X/* function: print branches that has the same direct ancestor */
X{
X
X if ( branchroot == nil ) return;
X
X putforest(branchroot->nextbranch);
X
X putabranch(branchroot->hsh);
X putree(branchroot->hsh);
X}
X
X
X
X
Xputabranch(root)
Xstruct hshentry *root;
X/* function : print one branch */
X
X{
X
X if ( root == nil) return;
X
X putabranch(root->next);
X
X putadelta(root, root, false);
X}
X
X
X
X
X
Xputadelta(node,editscript,trunk)
Xregister struct hshentry * node;
Xregister struct hshentry * editscript;
Xint trunk;
X/* function: print delta node if node->selector is 's'. */
X/* editscript indicates where the editscript is stored */
X/* trunk indicated whether this node is in trunk */
X{
X struct branchhead * newbranch;
X char * branchnum, branch[40];
X
X if ( ( node == nil) || ( node->selector == 'u'))
X return;
X
X VOID fprintf(stdout,"----------------------------\n");
X VOID fprintf(stdout, "revision %s ",node->num);
X if ( node->lockedby )
X VOID fprintf(stdout, "locked by: %s; ", node->lockedby);
X VOID putc('\n', stdout);
X
X VOID fputs("date: ",stdout);
X VOID PRINTDATE(stdout,node->date); VOID putc(' ',stdout);
X VOID PRINTTIME(stdout,node->date);
X VOID fprintf(stdout, "; author: %s; ", node->author);
X VOID fprintf(stdout, "state: %s; ", node->state);
X
X if ( editscript )
X if(trunk)
X VOID fprintf(stdout,"lines added/del: %d/%d",
X editscript->deletelns, editscript->insertlns);
X else
X VOID fprintf(stdout,"lines added/del: %d/%d",
X editscript->insertlns, editscript->deletelns);
X
X VOID putc('\n', stdout);
X
X branchnum = & (branch[0]);
X newbranch = node->branches;
X if ( newbranch ) {
X VOID fputs("branches: ", stdout);
X while( newbranch ) {
X getbranchno(newbranch->hsh->num, branchnum);
X VOID fprintf(stdout, "%s; ", branchnum);
X newbranch = newbranch->nextbranch;
X }
X VOID putc('\n', stdout);
X }
X
X VOID fputs(node->log,stdout);
X}
X
X
X
X
X
Xreaddeltalog()
X/* Function : get the log message and skip the text of a deltatext node.
X * Return false if current block does not start with a number.
X * Assumes the current lexeme is not yet in nexttok; does not
X * advance nexttok.
X */
X{
X register struct hshentry * Delta;
X
X nextlex();
X if ( !(Delta = getnum() )) return(false);
X if ( ! getkey(Klog) || ( nexttok != STRING ) )
X fatserror("Missing log entry");
X Delta->log = talloc(logsize);
X VOID savestring(Delta->log, logsize);
X nextlex();
X if ( ! getkey(Ktext) || (nexttok != STRING) )
X fatserror("Missing delta text");
X Delta->insertlns = Delta->deletelns = 0;
X if ( Delta != Head)
X getscript(Delta);
X else
X readstring();
X return true;
X}
X
X
X
Xgetscript(Delta)
Xstruct hshentry * Delta;
X/* function: read edit script of Delta and count how many lines added */
X/* and deleted in the script */
X
X{
X int ed; /* editor command */
X register FILE * fin;
X register int c;
X register int i;
X int length;
X
X fin = finptr;
X while( (ed = getc(fin)) != EOF) {
X /* assume first none white character is command name */
X while( ed == '\n' || ed == ' ' || ed == '\t')
X ed = getc(fin);
X if (ed == SDELIM) break; /* script text is ended */
X while( ( c = getc(fin)) == ' ' ); /* skip blank */
X if ( ! ('0' <= c && c <= '9')) {
X faterror("Missing line number in edit script");
X break;
X }
X while( '0' <= (c = getc(fin)) && c <= '9' ) ;
X
X while( c == ' ')c = getc(fin); /* skip blanks */
X if ( !('0' <= c && c <= '9' ) ) {
X faterror("Incorrect range in edit script");
X break;
X }
X length = c - '0';
X while( '0' <= (c = getc(fin)) && c <= '9' )
X length = length * 10 + c - '0';
X while( c != '\n' && c != EOF) c = getc(fin);
X switch (ed) {
X case 'd' :
X Delta->deletelns += length;
X break;
X
X case 'a' :
X /* skip scripted lines */
X for ( i=length; i > 0 && c != EOF; i--){
X while( (c=getc(fin)) != '\n' && c != EOF);
X Delta->insertlns++;
X }
X break;
X
X default:
X faterror("Unknown command in edit script: %c", ed);
X break;
X }
X }
X nextc = getc(fin);
X}
X
X
X
X
X
X
X
Xexttree(root)
Xstruct hshentry *root;
X/* function: select revisions , starting with root */
X
X{
X struct branchhead * newbranch;
X
X if (root == nil) return;
X
X extractdelta(root);
X exttree(root->next);
X
X newbranch = root->branches;
X while( newbranch ) {
X exttree(newbranch->hsh);
X newbranch = newbranch->nextbranch;
X }
X}
X
X
X
X
Xgetlocker(argv)
Xchar * argv;
X/* function : get the login names of lockers from command line */
X/* and store in lockerlist. */
X
X{
X register char c;
X struct lockers * newlocker;
X argv--;
X while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
X c == '\n' || c == ';') ;
X if ( c == '\0') {
X lockerlist=nil;
X return;
X }
X
X while( c != '\0' ) {
X newlocker = ( struct lockers *)talloc( sizeof(struct lockers) );
X newlocker->lockerlink = lockerlist;
X newlocker->login = argv;
X lockerlist = newlocker;
X while ( ( c = (*++argv)) != ',' && c != '\0' && c != ' '
X && c != '\t' && c != '\n' && c != ';') ;
X *argv = '\0';
X if ( c == '\0' ) return;
X while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
X c == '\n' || c == ';') ;
X }
X}
X
X
X
Xgetauthor(argv)
Xchar *argv;
X/* function: get the author's name form command line */
X/* and store in aauthorlist */
X
X{
X register c;
X struct authors * newauthor;
X
X argv--;
X while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
X c == '\n' || c == ';') ;
X if ( c == '\0' ) {
X authorlist = (struct authors *)talloc(sizeof(struct authors));
X authorlist->login = caller;
X authorlist->nextauthor = nil;
X return;
X }
X
X while( c != '\0' ) {
X newauthor = (struct authors *)talloc(sizeof(struct authors));
X newauthor->nextauthor = authorlist;
X newauthor->login = argv;
X authorlist = newauthor;
X while( ( c = *++argv) != ',' && c != '\0' && c != ' '
X && c != '\t' && c != '\n' && c != ';') ;
X * argv = '\0';
X if ( c == '\0') return;
X while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
X c == '\n' || c == ';') ;
X }
X}
X
X
X
X
Xgetstate(argv)
Xchar * argv;
X/* function : get the states of revisions from command line */
X/* and store in statelist */
X
X{
X register char c;
X struct stateattri *newstate;
X
X argv--;
X while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
X c == '\n' || c == ';') ;
X if ( c == '\0'){
X warn(" Missing state attributes after -s options");
X return;
X }
X
X while( c != '\0' ) {
X newstate = (struct stateattri *)talloc(sizeof(struct stateattri));
X newstate->nextstate = statelist;
X newstate->status = argv;
X statelist = newstate;
X while( (c = (*++argv)) != ',' && c != '\0' && c != ' '
X && c != '\t' && c != '\n' && c != ';') ;
X *argv = '\0';
X if ( c == '\0' ) return;
X while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
X c == '\n' || c == ';') ;
X }
X}
X
X
X
Xtrunclocks()
X/* Function: Truncate the list of locks to those that are held by the */
X/* id's on lockerlist. Do not truncate if lockerlist empty. */
X
X{
X struct lockers * plocker;
X struct lock * plocked, * nextlocked;
X
X if ( (lockerlist == nil) || (Locks == nil)) return;
X
X /* shorten Locks to those contained in lockerlist */
X plocked = Locks;
X Locks = nil;
X while( plocked != nil) {
X plocker = lockerlist;
X while((plocker != nil) && ( strcmp(plocker->login, plocked->login)!=0))
X plocker = plocker->lockerlink;
X nextlocked = plocked->nextlock;
X if ( plocker != nil) {
X plocked->nextlock = Locks;
X Locks = plocked;
X }
X plocked = nextlocked;
X }
X}
X
X
X
Xrecentdate(root, pd)
Xstruct hshentry * root;
Xstruct Datepairs * pd;
X/* function: Finds the delta that is closest to the cutoff date given by */
X/* pd among the revisions selected by exttree. */
X/* Successively narrows down the interfal given by pd, */
X/* and sets the strtdate of pd to the date of the selected delta */
X{
X struct branchhead * newbranch;
X
X if ( root == nil) return;
X if ( root->selector == 's') {
X if ( cmpnum(root->date, pd->strtdate) >= 0 &&
X cmpnum(root->date, pd->enddate) <= 0)
X VOID strcpy(pd->strtdate, root->date);
X }
X
X recentdate(root->next, pd);
X newbranch = root->branches;
X while( newbranch) {
X recentdate(newbranch->hsh, pd);
X newbranch = newbranch->nextbranch;
X }
X}
X
X
X
X
X
X
Xextdate(root)
Xstruct hshentry * root;
X/* function: select revisions which are in the date range specified */
X/* in duelst and datelist, start at root */
X
X{
X struct branchhead * newbranch;
X struct Datepairs * pdate;
X
X if ( root == nil) return;
X
X if ( datelist || duelst) {
X pdate = datelist;
X while( pdate ) {
X if ( (pdate->strtdate)[0] == '\0' || cmpnum(root->date,pdate->strtdate) >= 0){
X if ((pdate->enddate)[0] == '\0' || cmpnum(pdate->enddate,root->date) >= 0)
X break;
X }
X pdate = pdate->dnext;
X }
X if ( pdate == nil) {
X pdate = duelst;
X while(pdate) {
X if ( cmpnum(root->date, pdate->strtdate) == 0)
X break;
X pdate = pdate->dnext;
X }
X }
X if ( pdate == nil)
X root->selector = 'u';
X }
X if (root->selector == 's') revno++;
X
X extdate(root->next);
X
X newbranch = root->branches;
X while( newbranch ) {
X extdate(newbranch->hsh);
X newbranch = newbranch->nextbranch;
X }
X}
X
X
X
Xextractdelta(pdelta)
Xstruct hshentry * pdelta;
X/* function: compare information of pdelta to the authorlst, lockerlist, */
X/* statelist, revlist and mark 's' on selector if pdelta is */
X/* selected; otherwise, mark 'u' */
X
X{
X struct lock * plock;
X struct stateattri * pstate;
X struct authors * pauthor;
X struct Revpairs * prevision;
X int length;
X
X pdelta->selector = 's';
X if ( authorlist ) { /* certain author's revisions wanted only */
X pauthor = authorlist;
X while((pauthor != nil) && ( strcmp(pauthor->login, pdelta->author)!=0))
X pauthor = pauthor->nextauthor;
X if ( pauthor == nil ) {
X pdelta->selector = 'u';
X return;
X }
X }
X if ( statelist ) { /* revisions with certain state wanted */
X pstate = statelist;
X while((pstate != nil) && (strcmp(pstate->status, pdelta->state)!=0))
X pstate = pstate->nextstate;
X if ( pstate == nil ) {
X pdelta->selector = 'u';
X return;
X }
X }
X if ( lockflag ) { /* locked revisions */
X plock = Locks;
X while( plock && (plock->delta != pdelta))
X plock = plock->nextlock;
X if (plock == nil ) {
X pdelta->selector = 'u';
X return;
X }
X }
X if ( Revlst ) { /* revisions or branches selected */
X
X prevision = Revlst;
X while( prevision != nil ) {
X length = prevision->numfld;
X if ( length % 2 == 1) { /* a branch number */
X if ( countnumflds(pdelta->num) ==(length+1))
X if ( (compartial(pdelta->num, prevision->strtrev,length) >= 0)&&
X (compartial(prevision->endrev, pdelta->num, length) >= 0) )
X break;
X }
X else if ( countnumflds(pdelta->num ) == length) /* a revision */
X if ( (compartial(pdelta->num, prevision->strtrev, length) >= 0) &&
X (compartial(prevision->endrev, pdelta->num, length) >= 0) )
X break;
X prevision = prevision->rnext;
X }
X if (prevision == nil) {
X pdelta->selector = 'u';
X return;
X }
X }
X}
X
X
X
Xchar * procdate(target, source)
Xchar * target, * source;
X/* Function: Parses a free-format date in target, converts it
X * into RCS internal format, and stores the result into source.
X * Returns target on success, nil otherwise.
X */
X{
X long unixtime;
X struct tm parseddate, *ftm;
X
X if ( partime(source, &parseddate) == 0) {
X error("Can't parse date/time: %s", source);
X *target= '\0';
X return nil;
X }
X if ( (unixtime = maketime(&parseddate)) == 0L) {
X error("Inconsistent date/time: %s", source);
X *target='\0';
X return nil;
X }
X ftm = localtime(&unixtime);
X VOID sprintf(target,DATEFORM,
X ftm->tm_year,ftm->tm_mon+1,ftm->tm_mday,ftm->tm_hour,ftm->tm_min,ftm->tm_sec);
X return target;
X}
X
X
X
Xgetdatepair(argv)
X char * argv;
X/* function: get time range from command line and store in datelist if */
X/* a time range specified or in duelst if a time spot specified */
X
X{
X register char c;
X struct Datepairs * nextdate;
X char * rawdate;
X int switchflag;
X
X argv--;
X while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
X c == '\n' || c == ';') ;
X if ( c == '\0' ) {
X warn("Missing date/time after -d");
X return;
X }
X
X while( c != '\0' ) {
X switchflag = false;
X nextdate = (struct Datepairs *) talloc(sizeof(struct Datepairs));
X if ( c == '<' ) { /* case: -d <date */
X c = *++argv;
X (nextdate->strtdate)[0] = '\0';
X } elsif (c == '>') { /* case: -d >date */
X c = *++argv;
X (nextdate->enddate)[0] = '\0';
X switchflag = true;
X } else {
X rawdate = argv;
X while( c != '<' && c != '>' && c != ';' && c != '\0')
X c = *++argv;
X *argv = '\0';
X if ( c == '>' ) switchflag=true;
X if (procdate(switchflag?nextdate->enddate:nextdate->strtdate,
X rawdate)==nil) continue;
X if ( c == ';' || c == '\0') { /* case: -d date */
X VOID strcpy(nextdate->enddate,nextdate->strtdate);
X VOID sprintf(nextdate->strtdate,DATEFORM,0,0,0,0,0,0);
X nextdate->dnext = duelst;
X duelst = nextdate;
X goto end;
X } else {
X /* case: -d date< or -d date>; see switchflag */
X while ( (c= *++argv) == ' ' || c=='\t' || c=='\n');
X if ( c == ';' || c == '\0') {
X /* second date missing */
X if (switchflag)
X *nextdate->strtdate= '\0';
X else
X *nextdate->enddate= '\0';
X nextdate->dnext = datelist;
X datelist = nextdate;
X goto end;
X }
X }
X }
X rawdate = argv;
X while( c != '>' && c != '<' && c != ';' && c != '\0')
X c = *++argv;
X *argv = '\0';
X if (procdate(switchflag?nextdate->strtdate:nextdate->enddate,
X rawdate)==nil) continue;
X nextdate->dnext = datelist;
X datelist = nextdate;
X end:
X/*
X VOID printf("startdate: %s; enddate: %s;\n", nextdate->strtdate,nextdate->enddate);
X*/
X if ( c == '\0') return;
X while( (c = *++argv) == ';' || c == ' ' || c == '\t' || c =='\n');
X }
X}
X
X
X
X
X
Xgetnumericrev()
X/* function: get the numeric name of revisions which stored in revlist */
X/* and then stored the numeric names in Revlst */
X/* if branchflag, also add default branch */
X
X{
X struct Revpairs * ptr, *pt;
X int flag;
X char *temprev;
X
X /* free the previous numeric revision list */
X pt = Revlst;
X while( pt) {
X ptr = pt->rnext;
X free((char *)pt);
X pt = ptr;
X }
X Nextdotstring = &Dotstring[0]; /* reset buffer */
X
X
X Revlst = nil;
X ptr = revlist;
X while( ptr ) {
X pt = (struct Revpairs *) talloc(sizeof(struct Revpairs));
X if ( ptr->numfld == 1 ){ /* case: -r rev */
X if ( (flag = expandsym(ptr->strtrev, Nextdotstring)) == true ) {
X pt->numfld = countnumflds(Nextdotstring);
X pt->strtrev = pt->endrev = Nextdotstring;
X while( *Nextdotstring++ != '\0' ) ;
X }
X }
X else if( ptr->numfld == 2){ /* case: -r rev- */
X if ( (flag = expandsym(ptr->strtrev, Nextdotstring)) == true) {
X pt->numfld = countnumflds(Nextdotstring);
X pt->strtrev = Nextdotstring;
X while( *Nextdotstring++ != '\0' ) ;
X pt->endrev = Nextdotstring;
X if ( pt->numfld > 2) choptail(pt->strtrev);
X * Nextdotstring++ = '\0';
X }
X }
X else if(ptr->numfld == 3) { /* case: -r -rev */
X if ( (flag = expandsym(ptr->endrev, Nextdotstring)) == true) {
X pt->endrev = Nextdotstring;
X while( *Nextdotstring++ != '\0' ) ;
X pt->numfld = countnumflds(pt->endrev);
X pt->strtrev = Nextdotstring;
X if ( pt->numfld == 2)
X *Nextdotstring++ = '1';
X else
X choptail(pt->endrev);
X *Nextdotstring++ = '.';
X *Nextdotstring++ = '1';
X *Nextdotstring++ = '\0';
X }
X }
X else { /* case: -r rev1-rev2 */
X if ( (flag = expandsym(ptr->strtrev, Nextdotstring)) == true ) {
X pt->strtrev = Nextdotstring;
X while( *Nextdotstring++ != '\0' ) ;
X if ( ( flag = expandsym(ptr->endrev, Nextdotstring)) == true) {
X pt->numfld = countnumflds(pt->strtrev);
X pt->endrev = Nextdotstring;
X while( *Nextdotstring++ != '\0' ) ;
X if((flag = checkrevpair(pt->strtrev, pt->endrev)) == true)
X /* switch pt->strtrev with pt->endrev, if pt->strtrev > pt->endre */
X if (compartial(pt->strtrev, pt->endrev, pt->numfld) > 0 ) {
X temprev = pt->strtrev;
X pt->strtrev = pt->endrev;
X pt->endrev = temprev;
X }
X }
X }
X }
X
X if ( flag ){
X pt->rnext = Revlst;
X Revlst = pt;
X }
X else
X free((char *)pt);
X ptr = ptr->rnext;
X }
X /* Now take care of branchflag */
X if (branchflag) {
X flag =true;
X pt = (struct Revpairs *) talloc(sizeof(struct Revpairs));
X if (Dbranch) {
X pt->strtrev = pt->endrev = Dbranch->num;
X } elsif (Head!=nil) {
X pt->strtrev = pt->endrev = /* branch number of head */
X partialno(Nextdotstring,Head->num,1);
X while( *Nextdotstring++ != '\0' ) ;
X } else flag = false;
X if (flag) { /* prepend new node */
X pt->rnext=Revlst; Revlst=pt;
X pt->numfld = countnumflds(pt->strtrev);
X }
X }
X
X}
X
X
X
Xcheckrevpair(num1,num2)
Xchar *num1, *num2;
X/* function: check whether num1, num2 are legal pair,i.e.
X only the last field are different and have same number of
X feilds( if length <= 2, may be different if first field) */
X
X{
X int length;
X
X if ( (length = countnumflds(num1)) != countnumflds(num2) ) {
X error(" Invalid branch or revision pair %s : %s", num1, num2);
X return false;
X }
X if ( length > 2 )
X if (compartial(num1, num2, length-1) != 0) {
X error("Invalid branch or revision pair %s : %s", num1, num2);
X return false;
X }
X
X return true;
X}
X
X
X
Xgetrevpairs(argv)
Xregister char * argv;
X/* function: get revision or branch range from command line, and */
X/* store in revlist */
X
X{
X register char c;
X struct Revpairs * nextrevpair;
X int flag;
X
X argv--;
X while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
X c == '\n' || c == ';') ;
X if ( c == '\0' ) {
X warn(" Missing revision or branch number after -r");
X return;
X }
X
X while( c != '\0') {
X while( c == ',' || c == ' ' || c == '\t' ||
X c == '\n' || c == ';') c = *++argv;
X if (c == '\0') return;
X nextrevpair = (struct Revpairs *) talloc(sizeof(struct Revpairs));
X nextrevpair->rnext = revlist;
X revlist = nextrevpair;
X nextrevpair->numfld = nil;
X nextrevpair->strtrev = nil;
X nextrevpair->endrev = nil;
X flag = false;
X if ( c == '<' || c == '-' ) { /* case: -r -rev or -r <rev */
X flag = true;
X while( (c =(*++argv)) == ' ' || c == '\t' || c =='\n') ;
X }
X else {
X nextrevpair->strtrev = argv;
X /* get a revision or branch name */
X while( c != ',' && c != ';' && c != ' ' && c != '\0' && c != '-'
X && c != '\t' && c != '\n' && c != '<') c = *++argv;
X
X *argv = '\0';
X
X if ( c != '<' && c != '-') { /* case: rev */
X nextrevpair->numfld = 1;
X continue;
X }
X
X if ( (c =(*++argv)) == ',' || c == '\0' || c == ' '
X || c == '\t' || c == '\n' || c == ';') {/* case: rev_ */
X nextrevpair->numfld = 2;
X continue;
X }
X }
X nextrevpair->endrev = argv;
X while( c != ',' && c != ' ' && c != '\0' && c != '\t' && c != '<'
X && c != '\n' && c != '-' && c != ';') c = *++argv;
X
X * argv = '\0';
X if ( c == '<'){
X error("separator expected near %s", nextrevpair->endrev);
X while( (c = *++argv) != ',' && c != ' ' && c != '\0' &&
X c != '\t' && c != '\n' && c != ';' ) ;
X revlist = nextrevpair->rnext;
X continue;
X }
X else {
X if (flag) /* case: -rev */
X nextrevpair->numfld = 3;
X
X else /* rev1-rev2 appears */
X nextrevpair->numfld = 4;
X }
X }
X}
X
X
X
Xchoptail(strhead)
Xchar * strhead;
X/* function : chop off the last field of a branch or a revision number */
X
X{
X char *pt, *sp;
X
X for(pt = Nextdotstring-1; pt != strhead && *pt != '.'; pt--) ;
X for(sp = strhead; sp < pt; sp++) *Nextdotstring++ = *sp;
X}
X
X@
X
X
X4.7.2.1
Xlog
X@Start of Amiga RCS port branch.
X@
Xtext
X@d6 1
Xa6 5
X<<<<<<< rlog.c
X"$Header: /u/softeng/rsbx/rcs/amiga/RCS.cbmvax/rlog.c,v 4.7.1.1 89/08/11 01:43:14 rsbx Exp Locker: rsbx $ Purdue CS";
X=======
X"$Header: /u/softeng/rsbx/rcs/amiga/RCS/rlog.c,v 1.2 89/09/17 13:36:54 rick Exp $ Purdue CS";
X>>>>>>> 1.2
Xa41 16
X<<<<<<< rlog.c
X * Revision 4.7.1.1 89/08/11 01:43:14 rsbx
X * Start of cbmvax RCS source branch.
X *
X * Revision 4.7 89/05/01 15:13:48 narten
X * checked in with -k by rsbx at 89.08.10.16.23.28.
X=======
X * Revision 1.2 89/09/17 13:36:54 rick
X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
X * All changes done with conditional compile (#ifdef AMIGA). This version
X * compiles correctly with Lattice C version 5.02 or later.
X *
X * Revision 1.2 88/09/03 15:13:12 rick
X * Port to AmigaDos. All done with conditional compiles
X>>>>>>> 1.2
X *
X@
X
X
X4.7.2.2
Xlog
X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
Xsources I have here (and are later than the ones Rick used).
X@
Xtext
X@d6 5
Xa10 1
X"$Header: /u/softeng/rsbx/rcs/amiga/RCS/rlog.c,v 4.7.2.1 89/10/13 19:19:26 rsbx Exp Locker: rsbx $ Purdue CS";
Xd46 1
Xa46 3
X * Revision 4.7.2.1 89/10/13 19:19:26 rsbx
X * Start of Amiga RCS port branch.
X *
Xd52 9
X@
X
X
X4.7.1.1
Xlog
X@Start of cbmvax RCS source branch.
X@
Xtext
X@d6 1
Xa6 1
X"$Header: /u/softeng/rsbx/rcs/rcs.uunet/src/RCS/rlog.c,v 4.7 89/05/01 15:13:48 narten Exp $ Purdue CS";
Xa41 3
X * Revision 4.7 89/05/01 15:13:48 narten
X * checked in with -k by rsbx at 89.08.10.16.23.28.
X *
X@
SHAR_EOF
echo "End of archive 11 (of 14)"
# if you want to concatenate archives, remove anything after this line
exit